{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "import torchvision.datasets as dset\n",
    "from torch.distributions import Bernoulli\n",
    "import torchvision.transforms as transforms\n",
    "import numpy as np\n",
    "import random\n",
    "from matplotlib import pyplot as plt\n",
    "from scipy.stats import halfnorm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Reinforcement Learning _in Action_\n",
    "## MNIST Genetic Algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Setup a directory to store the MNIST dataset/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "root = './data'\n",
    "if not os.path.exists(root):\n",
    "    os.mkdir(root)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Setup a transformer to normalize the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to ./data/MNIST/raw/train-images-idx3-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████| 9912422/9912422 [00:08<00:00, 1196163.77it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data/MNIST/raw/train-images-idx3-ubyte.gz to ./data/MNIST/raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to ./data/MNIST/raw/train-labels-idx1-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████| 28881/28881 [00:00<00:00, 22109088.12it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data/MNIST/raw/train-labels-idx1-ubyte.gz to ./data/MNIST/raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw/t10k-images-idx3-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████| 1648877/1648877 [00:01<00:00, 1292398.41it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data/MNIST/raw/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████| 4542/4542 [00:00<00:00, 8038197.79it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "train_set = dset.MNIST(root=root, train=True, transform=trans, download=True)\n",
    "test_set = dset.MNIST(root=root, train=False, transform=trans, download=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 100\n",
    "\n",
    "train_loader = torch.utils.data.DataLoader(\n",
    "                 dataset=train_set,\n",
    "                 batch_size=batch_size,\n",
    "                 shuffle=True)\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "                dataset=test_set,\n",
    "                batch_size=batch_size,\n",
    "                shuffle=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We define a simple linear classifier (or you can think of it as a single layer neural network). It simply multiplies a weight/parameter matrix by the input vector and applies a softmax."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = next(iter(train_loader))[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = x.reshape(100,784)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Individual:\n",
    "    def __init__(self,param, fitness=0):\n",
    "        self.param = param\n",
    "        self.fitness = fitness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def model(x,W):\n",
    "    return torch.nn.Softmax()(x @ W)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/don/git/DeepReinforcementLearningInAction/venv/lib/python3.10/site-packages/torch/nn/modules/module.py:1511: UserWarning: Implicit dimension choice for softmax has been deprecated. Change the call to include dim=X as an argument.\n",
      "  return self._call_impl(*args, **kwargs)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([[2.7988e-02, 9.2476e-01, 2.8312e-02, 5.7766e-03, 3.1261e-04, 8.6586e-05,\n",
       "         7.4683e-07, 1.0717e-04, 3.0326e-05, 1.2625e-02],\n",
       "        [1.1727e-02, 9.1829e-01, 1.5762e-02, 3.3097e-03, 3.2942e-03, 7.6944e-04,\n",
       "         8.7624e-03, 6.2241e-04, 2.9262e-02, 8.2016e-03],\n",
       "        [7.9934e-01, 6.6551e-02, 3.5123e-02, 7.5844e-02, 6.6300e-04, 1.9790e-02,\n",
       "         7.0070e-07, 1.5790e-04, 1.5448e-04, 2.3762e-03],\n",
       "        [8.5457e-02, 9.1158e-01, 3.6383e-04, 1.4504e-03, 2.2931e-05, 6.0192e-04,\n",
       "         1.5989e-05, 2.5796e-04, 1.0023e-04, 1.4733e-04],\n",
       "        [9.3388e-01, 2.3687e-03, 1.1790e-03, 5.7466e-02, 6.1725e-04, 5.3604e-04,\n",
       "         1.6360e-07, 1.5933e-05, 2.7593e-03, 1.1742e-03],\n",
       "        [4.8667e-03, 9.8599e-02, 1.7211e-01, 5.8648e-01, 1.7908e-04, 4.0506e-02,\n",
       "         3.6000e-05, 4.7075e-04, 4.9481e-02, 4.7267e-02],\n",
       "        [2.9993e-01, 1.3598e-01, 8.0386e-03, 5.3354e-01, 2.6618e-03, 1.5952e-04,\n",
       "         9.0557e-04, 1.1860e-03, 4.6532e-03, 1.2945e-02],\n",
       "        [2.4034e-01, 4.8383e-01, 1.1624e-01, 8.2345e-02, 4.7858e-03, 6.6922e-02,\n",
       "         1.1793e-05, 2.4248e-04, 2.4327e-03, 2.8549e-03],\n",
       "        [7.5101e-02, 7.9598e-01, 4.6868e-03, 7.8001e-02, 1.1390e-03, 3.3590e-04,\n",
       "         7.2739e-04, 1.9484e-03, 2.6317e-02, 1.5759e-02],\n",
       "        [3.7047e-01, 3.3841e-02, 9.9279e-04, 9.9054e-02, 4.9452e-02, 4.1406e-01,\n",
       "         7.9806e-03, 5.1487e-03, 5.0587e-03, 1.3944e-02],\n",
       "        [3.7202e-01, 3.4961e-01, 2.9385e-02, 1.0329e-01, 6.6566e-03, 1.2609e-01,\n",
       "         1.3931e-06, 8.6646e-03, 3.4321e-03, 8.4015e-04],\n",
       "        [4.8603e-01, 2.5375e-02, 2.8300e-01, 1.1196e-01, 1.4914e-03, 5.8615e-02,\n",
       "         2.7102e-07, 3.1493e-02, 1.4427e-03, 5.9013e-04],\n",
       "        [9.3542e-01, 2.4221e-03, 6.5208e-04, 3.2151e-02, 1.3700e-03, 7.4728e-05,\n",
       "         2.9960e-05, 1.0431e-03, 2.7715e-04, 2.6557e-02],\n",
       "        [2.0475e-03, 9.7593e-01, 4.8786e-04, 2.1466e-02, 1.5732e-05, 1.9375e-05,\n",
       "         8.0954e-08, 5.8644e-06, 5.0159e-06, 2.4099e-05],\n",
       "        [3.7378e-01, 5.7183e-01, 6.3882e-03, 3.0805e-03, 3.0438e-02, 9.7105e-04,\n",
       "         5.6609e-04, 2.7311e-04, 1.7953e-03, 1.0871e-02],\n",
       "        [1.1995e-02, 9.8133e-01, 1.7418e-04, 2.7897e-04, 5.0370e-03, 1.7871e-04,\n",
       "         1.1592e-04, 5.3222e-05, 1.1610e-04, 7.1687e-04],\n",
       "        [9.6034e-03, 1.1875e-01, 2.2373e-01, 6.4638e-01, 8.7277e-05, 2.2660e-05,\n",
       "         2.2855e-06, 1.2523e-05, 1.4015e-03, 1.9031e-05],\n",
       "        [4.9973e-01, 1.2228e-02, 4.4713e-03, 4.7099e-01, 1.5279e-05, 1.6875e-04,\n",
       "         6.5396e-06, 9.0488e-03, 2.3536e-03, 9.8573e-04],\n",
       "        [8.1872e-03, 9.5637e-01, 8.5150e-03, 8.7448e-05, 2.5842e-02, 1.3225e-04,\n",
       "         6.1234e-05, 3.4310e-04, 1.1949e-04, 3.4631e-04],\n",
       "        [2.0103e-02, 9.4294e-01, 3.1306e-02, 1.3870e-03, 2.9450e-05, 6.5246e-05,\n",
       "         5.5806e-07, 4.6505e-04, 1.9382e-04, 3.5072e-03],\n",
       "        [8.6097e-02, 5.8410e-03, 3.8532e-01, 4.9271e-01, 1.6522e-04, 2.0271e-02,\n",
       "         1.8709e-04, 5.0118e-05, 9.2893e-03, 6.5712e-05],\n",
       "        [5.3268e-01, 4.3336e-01, 1.5621e-02, 6.2046e-03, 9.0200e-03, 1.9586e-03,\n",
       "         7.4844e-07, 5.3389e-04, 1.0674e-04, 5.1340e-04],\n",
       "        [5.9433e-03, 9.8936e-01, 2.3726e-03, 1.7168e-03, 1.3709e-06, 2.6123e-04,\n",
       "         1.5834e-05, 2.2111e-06, 2.2714e-06, 3.1964e-04],\n",
       "        [2.1867e-01, 6.5368e-01, 3.2843e-03, 7.4376e-02, 1.8185e-03, 2.3459e-03,\n",
       "         4.4252e-04, 1.2705e-03, 3.5658e-02, 8.4600e-03],\n",
       "        [1.7324e-01, 5.1678e-01, 1.6366e-01, 5.2131e-02, 3.0429e-04, 8.7195e-02,\n",
       "         6.3313e-07, 4.8192e-04, 4.7221e-04, 5.7349e-03],\n",
       "        [3.7504e-01, 5.4302e-03, 1.6203e-03, 5.8099e-01, 4.9077e-03, 1.4154e-02,\n",
       "         2.8281e-03, 1.0259e-02, 2.5350e-03, 2.2374e-03],\n",
       "        [1.0605e-01, 7.5449e-01, 3.3160e-03, 1.1890e-01, 1.9425e-03, 1.3317e-02,\n",
       "         1.0252e-05, 5.5637e-04, 1.3834e-03, 3.2713e-05],\n",
       "        [1.1738e-02, 9.1099e-01, 4.1634e-02, 2.2926e-02, 9.5613e-05, 9.7395e-03,\n",
       "         5.2456e-06, 5.2877e-04, 5.5144e-04, 1.7907e-03],\n",
       "        [3.0590e-01, 3.2414e-01, 1.5123e-01, 2.0795e-01, 5.3588e-03, 5.3890e-04,\n",
       "         6.3444e-06, 3.5471e-04, 2.9403e-03, 1.5870e-03],\n",
       "        [7.3998e-03, 6.0460e-01, 3.4699e-01, 3.6728e-02, 6.4951e-05, 3.7104e-03,\n",
       "         1.1097e-06, 1.6417e-04, 3.2014e-04, 1.6271e-05],\n",
       "        [3.9374e-01, 5.7836e-01, 6.6583e-03, 1.1588e-02, 4.8586e-04, 1.8419e-03,\n",
       "         4.4088e-07, 6.9062e-05, 1.3612e-03, 5.9007e-03],\n",
       "        [7.5531e-01, 1.7531e-01, 8.7696e-04, 1.4202e-02, 2.0623e-03, 4.1171e-02,\n",
       "         1.1493e-03, 4.1249e-04, 7.3885e-03, 2.1147e-03],\n",
       "        [9.2635e-03, 9.5223e-01, 1.0543e-02, 2.1753e-02, 1.3715e-03, 4.5919e-04,\n",
       "         6.0621e-05, 5.3983e-05, 2.5742e-03, 1.6948e-03],\n",
       "        [1.0460e-01, 7.8333e-01, 4.5598e-02, 7.0820e-04, 5.2773e-03, 1.8351e-02,\n",
       "         2.4484e-05, 2.7105e-03, 2.9514e-02, 9.8886e-03],\n",
       "        [7.0495e-03, 9.7865e-01, 2.0733e-03, 1.9493e-04, 9.4404e-03, 9.2086e-05,\n",
       "         1.8819e-06, 1.4242e-04, 2.8870e-05, 2.3281e-03],\n",
       "        [9.8314e-01, 1.8584e-03, 9.6638e-04, 1.6923e-03, 1.5455e-05, 2.3965e-04,\n",
       "         1.8115e-06, 7.9079e-06, 1.2053e-02, 2.7917e-05],\n",
       "        [2.2095e-01, 6.6557e-01, 6.6399e-02, 2.8580e-02, 2.6655e-03, 8.4691e-03,\n",
       "         1.6092e-05, 8.1822e-04, 5.6342e-03, 8.9749e-04],\n",
       "        [2.1514e-02, 9.7244e-01, 7.2101e-04, 1.2352e-03, 3.8963e-04, 4.9260e-04,\n",
       "         3.5003e-04, 5.4118e-04, 7.9781e-04, 1.5168e-03],\n",
       "        [1.0161e-02, 8.5247e-01, 2.3017e-02, 3.3210e-02, 4.0687e-04, 9.1576e-03,\n",
       "         9.5777e-05, 1.6161e-02, 1.6017e-04, 5.5163e-02],\n",
       "        [7.9407e-01, 1.4356e-01, 2.3195e-02, 3.4865e-02, 1.2331e-04, 2.0640e-03,\n",
       "         3.1798e-07, 1.4677e-03, 5.8093e-04, 6.8949e-05],\n",
       "        [1.3184e-02, 9.5788e-01, 4.6697e-03, 6.7727e-03, 6.0061e-04, 9.4261e-05,\n",
       "         9.8289e-05, 2.7793e-05, 5.5947e-03, 1.1074e-02],\n",
       "        [3.9309e-01, 5.5534e-01, 3.5861e-02, 7.0278e-03, 8.8388e-05, 7.4785e-03,\n",
       "         4.7545e-07, 3.1300e-04, 9.9259e-05, 6.9554e-04],\n",
       "        [8.6388e-01, 3.4587e-02, 5.1888e-04, 8.7794e-02, 4.7435e-03, 2.2924e-04,\n",
       "         3.5134e-04, 1.1717e-03, 3.0010e-03, 3.7265e-03],\n",
       "        [9.5885e-01, 1.4483e-02, 1.4430e-02, 2.5186e-03, 1.0640e-03, 1.1394e-03,\n",
       "         7.5173e-05, 7.4881e-04, 6.6155e-03, 7.4889e-05],\n",
       "        [4.0321e-01, 2.7564e-01, 1.5955e-02, 3.7922e-03, 1.4261e-02, 2.4205e-04,\n",
       "         2.9686e-05, 1.6594e-03, 2.1711e-04, 2.8500e-01],\n",
       "        [1.4032e-01, 5.0354e-02, 5.5555e-02, 1.9979e-01, 2.0862e-03, 2.3895e-03,\n",
       "         9.9947e-05, 2.1251e-03, 3.9977e-04, 5.4689e-01],\n",
       "        [3.3291e-01, 5.7686e-01, 2.2905e-02, 6.4046e-03, 1.7323e-02, 1.1186e-02,\n",
       "         4.4525e-04, 1.3642e-03, 2.3058e-02, 7.5442e-03],\n",
       "        [8.5510e-02, 1.3548e-01, 7.0160e-02, 6.7719e-01, 6.5128e-03, 3.0660e-05,\n",
       "         1.5008e-04, 3.2489e-04, 2.1409e-02, 3.2315e-03],\n",
       "        [7.6177e-02, 8.9778e-01, 5.9292e-03, 1.7652e-02, 2.6974e-05, 2.1610e-03,\n",
       "         1.2985e-06, 1.0459e-04, 4.9049e-05, 1.1422e-04],\n",
       "        [1.2016e-01, 2.2813e-03, 8.4806e-02, 5.8295e-01, 1.7562e-05, 9.7919e-05,\n",
       "         2.5544e-06, 3.6272e-04, 2.0928e-01, 5.0265e-05],\n",
       "        [7.3195e-02, 9.1937e-01, 3.2669e-03, 1.1572e-03, 2.7806e-04, 7.1638e-05,\n",
       "         4.6884e-07, 5.0210e-05, 3.0845e-04, 2.2999e-03],\n",
       "        [1.0837e-01, 5.3273e-01, 5.7104e-03, 4.7121e-02, 1.1419e-03, 8.4297e-04,\n",
       "         1.0061e-03, 7.5065e-03, 1.4168e-03, 2.9415e-01],\n",
       "        [6.9411e-02, 4.8520e-01, 4.2764e-01, 1.1852e-02, 2.3112e-04, 8.1047e-04,\n",
       "         1.4129e-06, 1.2975e-03, 6.0124e-05, 3.5015e-03],\n",
       "        [9.7106e-01, 1.7418e-02, 1.3138e-04, 9.7416e-03, 7.9039e-04, 2.5621e-05,\n",
       "         3.9321e-06, 3.6996e-05, 4.1360e-04, 3.7365e-04],\n",
       "        [8.3596e-01, 1.2149e-01, 4.3467e-03, 1.2176e-02, 8.4751e-03, 7.2550e-04,\n",
       "         7.2769e-04, 1.2780e-04, 9.0044e-03, 6.9738e-03],\n",
       "        [9.1970e-01, 5.1068e-02, 5.3421e-04, 2.7660e-03, 1.4056e-03, 6.8603e-04,\n",
       "         1.6135e-04, 7.5665e-05, 2.0696e-02, 2.9118e-03],\n",
       "        [8.2926e-01, 2.6309e-02, 4.8176e-03, 2.7271e-02, 1.3177e-03, 7.5973e-02,\n",
       "         1.3266e-05, 7.2175e-04, 3.2527e-02, 1.7936e-03],\n",
       "        [4.6345e-01, 4.6971e-01, 7.3113e-03, 7.3401e-03, 1.4622e-03, 1.0859e-03,\n",
       "         7.0994e-05, 7.7204e-03, 1.4915e-03, 4.0357e-02],\n",
       "        [8.0189e-02, 2.1937e-01, 8.7469e-02, 2.8501e-01, 4.8147e-03, 2.5399e-04,\n",
       "         1.3397e-03, 7.6974e-04, 1.1075e-01, 2.1002e-01],\n",
       "        [7.2939e-01, 6.9914e-03, 4.7141e-03, 1.9849e-01, 1.5684e-02, 6.5705e-03,\n",
       "         8.3176e-05, 5.3919e-03, 3.1843e-02, 8.4135e-04],\n",
       "        [5.7113e-01, 4.0609e-01, 2.9997e-04, 2.1372e-02, 9.9053e-05, 1.6626e-04,\n",
       "         7.7545e-06, 2.3584e-04, 2.8327e-04, 3.1340e-04],\n",
       "        [1.5679e-01, 8.3852e-01, 9.8214e-05, 3.0148e-03, 4.6465e-05, 1.2274e-05,\n",
       "         1.1272e-05, 9.1220e-06, 6.8115e-04, 8.1950e-04],\n",
       "        [2.2512e-01, 2.1756e-01, 3.9590e-01, 1.2758e-01, 2.2819e-02, 1.8866e-04,\n",
       "         2.6917e-05, 1.8067e-04, 3.9653e-03, 6.6579e-03],\n",
       "        [9.0080e-01, 8.9011e-02, 3.4923e-04, 7.7714e-03, 8.6201e-05, 1.5651e-04,\n",
       "         2.3872e-06, 7.0969e-04, 7.5135e-04, 3.5820e-04],\n",
       "        [9.3834e-01, 3.9562e-03, 6.8730e-04, 4.5449e-02, 1.3724e-03, 3.2233e-04,\n",
       "         4.6818e-05, 1.1562e-04, 8.8452e-03, 8.6090e-04],\n",
       "        [2.5024e-02, 1.7527e-01, 9.9358e-03, 7.8223e-01, 1.6651e-05, 4.0892e-03,\n",
       "         1.8355e-06, 9.1534e-05, 2.7056e-03, 6.3399e-04],\n",
       "        [9.6987e-02, 7.8229e-02, 8.3448e-02, 1.8838e-02, 6.7763e-01, 3.6586e-04,\n",
       "         1.5585e-03, 2.6448e-04, 1.1736e-03, 4.1504e-02],\n",
       "        [9.0812e-01, 1.4756e-02, 1.9525e-02, 3.2163e-02, 3.2422e-04, 1.3074e-02,\n",
       "         3.8975e-06, 4.6088e-03, 7.3792e-03, 4.3116e-05],\n",
       "        [5.3897e-01, 2.5086e-01, 1.3517e-02, 1.9301e-01, 1.8546e-05, 2.2942e-03,\n",
       "         2.5474e-07, 3.5570e-05, 4.5148e-05, 1.2589e-03],\n",
       "        [1.5765e-03, 9.9736e-01, 3.0302e-04, 3.3522e-04, 3.6091e-05, 5.2803e-05,\n",
       "         5.0484e-06, 4.8817e-06, 6.2249e-05, 2.6625e-04],\n",
       "        [7.2508e-03, 9.7563e-01, 1.6366e-03, 1.0521e-02, 7.0999e-05, 1.9370e-05,\n",
       "         8.7313e-06, 4.9068e-05, 1.9358e-04, 4.6233e-03],\n",
       "        [8.9402e-01, 2.2917e-02, 3.1558e-03, 7.4573e-02, 5.5549e-05, 5.2072e-04,\n",
       "         3.8440e-06, 7.6550e-05, 1.6247e-03, 3.0539e-03],\n",
       "        [8.6049e-01, 1.0594e-01, 4.3422e-04, 2.7249e-02, 2.1282e-03, 3.2550e-03,\n",
       "         4.2999e-06, 3.2828e-06, 4.2082e-05, 4.5254e-04],\n",
       "        [3.0535e-02, 9.3298e-01, 1.7627e-03, 3.1167e-02, 4.6050e-05, 1.6266e-04,\n",
       "         5.1992e-05, 1.1424e-04, 2.3063e-03, 8.7489e-04],\n",
       "        [9.8941e-01, 3.2990e-03, 2.0609e-03, 3.1292e-04, 4.7586e-05, 1.4192e-04,\n",
       "         2.4126e-08, 1.9984e-04, 4.5177e-03, 7.1552e-06],\n",
       "        [1.6406e-02, 6.7993e-01, 4.7180e-03, 2.7206e-01, 2.9321e-03, 2.8106e-05,\n",
       "         5.2356e-06, 6.4744e-05, 1.5481e-02, 8.3706e-03],\n",
       "        [8.2937e-01, 1.0095e-01, 8.9817e-03, 4.1795e-02, 2.0303e-03, 1.0243e-02,\n",
       "         7.1102e-05, 1.7639e-03, 3.9207e-03, 8.7040e-04],\n",
       "        [1.8089e-01, 5.8664e-01, 3.3891e-02, 1.7688e-01, 2.3276e-03, 4.1789e-03,\n",
       "         4.4113e-04, 2.1526e-03, 1.1401e-02, 1.1936e-03],\n",
       "        [8.5302e-01, 9.2270e-02, 6.0709e-03, 3.4102e-02, 1.3667e-04, 7.0179e-04,\n",
       "         7.5298e-05, 2.9533e-04, 9.3186e-03, 4.0082e-03],\n",
       "        [2.7100e-01, 1.9653e-02, 4.3131e-02, 6.3118e-01, 6.3474e-04, 5.7471e-03,\n",
       "         1.8805e-04, 8.8908e-04, 2.5241e-02, 2.3407e-03],\n",
       "        [9.0043e-01, 1.4801e-02, 7.2607e-03, 5.9797e-02, 5.0437e-05, 2.4524e-03,\n",
       "         8.7220e-06, 6.6932e-03, 8.3556e-03, 1.4910e-04],\n",
       "        [6.2002e-01, 3.7474e-01, 5.2334e-04, 2.9364e-03, 1.1297e-03, 5.8717e-05,\n",
       "         1.0414e-05, 1.7066e-05, 2.3252e-04, 3.2920e-04],\n",
       "        [8.3772e-01, 4.1029e-02, 1.6870e-04, 1.0463e-01, 2.1851e-03, 8.6542e-03,\n",
       "         1.4161e-04, 4.2182e-04, 2.0276e-03, 3.0205e-03],\n",
       "        [1.6073e-02, 5.9784e-01, 3.6434e-01, 1.2385e-02, 1.1161e-04, 1.7163e-03,\n",
       "         1.2109e-05, 6.5098e-05, 3.9280e-03, 3.5297e-03],\n",
       "        [2.6108e-01, 6.9634e-01, 2.3334e-02, 3.4346e-03, 1.0446e-03, 4.1833e-03,\n",
       "         1.4817e-05, 8.7162e-03, 1.6325e-03, 2.1510e-04],\n",
       "        [1.9527e-01, 7.8920e-01, 9.2121e-03, 1.4738e-03, 1.0729e-03, 3.2465e-05,\n",
       "         4.5569e-07, 3.4033e-03, 2.5517e-05, 3.0834e-04],\n",
       "        [9.3969e-01, 6.8670e-04, 2.9368e-02, 8.9107e-03, 1.0640e-04, 3.9312e-03,\n",
       "         3.6311e-05, 6.0918e-04, 1.6460e-02, 2.0251e-04],\n",
       "        [5.1472e-01, 2.2245e-01, 2.1579e-01, 1.8642e-02, 3.0290e-04, 2.5452e-02,\n",
       "         1.2674e-07, 9.5780e-04, 1.6812e-03, 6.0959e-06],\n",
       "        [6.3710e-03, 5.6793e-01, 1.8647e-01, 1.5316e-01, 2.4464e-02, 2.9308e-02,\n",
       "         3.0118e-05, 6.3178e-06, 6.0691e-03, 2.6190e-02],\n",
       "        [8.3681e-01, 1.5193e-01, 5.5928e-04, 7.2157e-03, 1.2402e-03, 3.5531e-04,\n",
       "         2.5100e-06, 1.0196e-03, 8.8791e-05, 7.7883e-04],\n",
       "        [3.1993e-01, 6.0267e-01, 8.7614e-05, 7.1469e-02, 1.7005e-04, 4.6948e-03,\n",
       "         6.2005e-06, 4.7526e-04, 2.6460e-04, 2.3186e-04],\n",
       "        [1.3798e-01, 8.4928e-01, 2.1796e-03, 4.4654e-03, 6.8257e-05, 1.0480e-03,\n",
       "         6.7516e-06, 5.9620e-04, 8.3075e-04, 3.5411e-03],\n",
       "        [5.4199e-01, 1.8051e-01, 1.6640e-03, 2.6760e-01, 6.6408e-03, 6.1406e-05,\n",
       "         5.5723e-06, 5.5624e-05, 6.9276e-04, 7.7933e-04],\n",
       "        [7.2478e-01, 7.5089e-03, 6.5652e-02, 1.8251e-01, 5.2839e-05, 2.4028e-03,\n",
       "         4.8239e-05, 2.0167e-03, 1.4941e-02, 8.6270e-05],\n",
       "        [6.8222e-01, 4.0088e-02, 5.2161e-04, 2.5321e-01, 1.3471e-03, 1.1130e-02,\n",
       "         2.7955e-04, 3.8195e-04, 1.0686e-02, 1.3994e-04],\n",
       "        [1.4406e-02, 9.5614e-01, 2.8227e-04, 2.7118e-02, 5.2172e-04, 3.0296e-04,\n",
       "         3.3306e-05, 6.3699e-04, 2.9382e-04, 2.6409e-04],\n",
       "        [6.0878e-01, 3.6382e-01, 4.8436e-03, 3.0899e-03, 9.2064e-04, 8.9208e-04,\n",
       "         3.0934e-04, 2.1728e-03, 7.6586e-03, 7.5145e-03],\n",
       "        [5.6040e-01, 3.0436e-01, 1.4689e-02, 9.2105e-02, 1.2011e-03, 2.4623e-02,\n",
       "         1.2905e-05, 6.0689e-04, 7.8789e-04, 1.2140e-03],\n",
       "        [6.8282e-01, 1.8538e-01, 2.3172e-03, 9.7782e-02, 2.7628e-03, 4.0170e-03,\n",
       "         5.3378e-05, 1.7997e-03, 5.2222e-03, 1.7840e-02],\n",
       "        [5.0811e-01, 2.7065e-01, 3.5471e-03, 8.1615e-02, 8.0110e-02, 2.9781e-03,\n",
       "         1.6455e-05, 9.2245e-05, 4.5950e-04, 5.2416e-02]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model(x,torch.rand(784,10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def spawn_population(param_size=(784,10),pop_size=1000):\n",
    "    return [Individual(torch.randn(*param_size)) for i in range(pop_size)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "loss_fn = torch.nn.CrossEntropyLoss()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "random.randint(0,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate_population(pop):\n",
    "    avg_fit = 0 #avg population fitness\n",
    "    for individual in pop:\n",
    "        x,y = next(iter(train_loader))\n",
    "        pred = model(x.reshape(batch_size,784),individual.param)\n",
    "        loss = loss_fn(pred,y)\n",
    "        fit = loss\n",
    "        individual.fitness = 1.0 / fit\n",
    "        avg_fit += fit\n",
    "    avg_fit = avg_fit / len(pop)\n",
    "    return pop, avg_fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def recombine(x1,x2): #x1,x2 : Individual\n",
    "    w1 = x1.param.view(-1) #flatten\n",
    "    w2 = x2.param.view(-1)\n",
    "    cross_pt = random.randint(0,w1.shape[0])\n",
    "    child1 = torch.zeros(w1.shape)\n",
    "    child2 = torch.zeros(w1.shape)\n",
    "    child1[0:cross_pt] = w1[0:cross_pt]\n",
    "    child1[cross_pt:] = w2[cross_pt:]\n",
    "    child2[0:cross_pt] = w2[0:cross_pt]\n",
    "    child2[cross_pt:] = w1[cross_pt:]\n",
    "    child1 = child1.reshape(784,10)\n",
    "    child2 = child2.reshape(784,10)\n",
    "    c1 = Individual(child1)\n",
    "    c2 = Individual(child2)\n",
    "    return [c1,c2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mutate(pop, mut_rate=0.01):\n",
    "    param_shape = pop[0].param.shape\n",
    "    l = torch.zeros(*param_shape)\n",
    "    l[:] = mut_rate\n",
    "    m = Bernoulli(l)\n",
    "    for individual in pop:\n",
    "        mut_vector = m.sample() * torch.randn(*param_shape)\n",
    "        individual.param = mut_vector + individual.param\n",
    "    return pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def seed_next_population(pop,pop_size=1000, mut_rate=0.01):\n",
    "    new_pop = []\n",
    "    while len(new_pop) < pop_size: #until new pop is full\n",
    "        parents = random.choices(pop,k=2, weights=[x.fitness for x in pop])\n",
    "        offspring = recombine(parents[0],parents[1])\n",
    "        new_pop.extend(offspring)\n",
    "    new_pop = mutate(new_pop,mut_rate)\n",
    "    return new_pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "pop = spawn_population()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 55.6 s, sys: 46.2 ms, total: 55.6 s\n",
      "Wall time: 20.2 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "pop, avg_fit = evaluate_population(pop)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_pop = seed_next_population(pop)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(new_pop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we need to spawn a population of weight matrices, run the model using the different individuals, calculate the loss for each one, and then breed the ones with the highest fitness score (lowest loss)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_generations = 50\n",
    "population_size = 100\n",
    "mutation_rate = 0.001 # 1% mutation rate per generation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Main Evolution (Training) Loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "pop_fit = []\n",
    "pop = spawn_population(pop_size=population_size) #initial population\n",
    "for gen in range(num_generations):\n",
    "    # trainning\n",
    "    pop, avg_fit = evaluate_population(pop)\n",
    "    pop_fit.append(avg_fit) #record population average fitness\n",
    "    new_pop = seed_next_population(pop, pop_size=population_size, mut_rate=mutation_rate)\n",
    "    pop = new_pop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f7df434efe0>]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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VqzA+vXrsXnzZowfPz7i+zNnzoTZbI54zpubm9HS0kLPeYYIBoPweDz0XGeBSy65BJ9++imampr4x6xZs/Dtb3+b/z8959mjp6cH+/fvx4gRI7L7952WDZpIyosvviharVbx+eefFz/77DPxe9/7nlheXi62tbVpfWi6p7u7W/z444/Fjz/+WAQgPvnkk+LHH38sHj58WBRFUXz00UfF8vJy8dVXXxV37dolXnXVVeL48ePF/v5+jY9cn9x6661iWVmZuGXLFvH48eP8o6+vj9/m+9//vjhmzBhx8+bN4ocffijOnTtXnDt3roZHrV9+8IMfiFu3bhUPHjwo7tq1S/zBD34gCoIgvvXWW6Io0nOdC+TTW6JIz3kmueeee8QtW7aIBw8eFP/+97+Ll156qVhdXS22t7eLopi955qKnhzw9NNPi2PGjBEtFot4/vnnizt27ND6kAqCd955RwQw6OPmm28WRTE0tv7DH/5QHD58uGi1WsVLLrlEbG5u1vagdUys5xqAuHr1an6b/v5+8bbbbhMrKirE4uJi8eqrrxaPHz+u3UHrmO985zvi2LFjRYvFIg4bNky85JJLeMEjivRc54Loooee88yxdOlSccSIEaLFYhFHjhwpLl26VNy3bx//fraea0EURTE9rYggCIIgCCL/IU8PQRAEQRBDAip6CIIgCIIYElDRQxAEQRDEkICKHoIgCIIghgRU9BAEQRAEMSSgoocgCIIgiCEBFT0EQRAEQQwJqOghCIIgCGJIQEUPQRAEQRBDAip6CIIgCIIYElDRQxAEQRDEkICKHoIgCIIghgT/H8fZcJfbxJV5AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(pop_fit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(2.3625)\n"
     ]
    }
   ],
   "source": [
    "avg_loss = 0\n",
    "for i in range(len(pop)):\n",
    "    x,y = next(iter(train_loader))\n",
    "    pred = model(x.reshape(batch_size,784),pop[i].param)\n",
    "    loss = loss_fn(pred,y)\n",
    "    avg_loss += loss\n",
    "avg_loss /= len(pop)\n",
    "print(avg_loss)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Avg Loss new pop: 2.3336\n",
    "Avg Loss after 10 gens: 2.3435"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train with gradient-descent (comparison)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = torch.randn(784,10, requires_grad=True)\n",
    "optim = torch.optim.Adam(lr=0.1, params=[p])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(2.2609, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2409, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1612, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1011, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2305, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1408, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2312, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1411, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1711, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1588, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2111, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1912, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1711, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2008, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2110, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2610, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1912, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1311, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1512, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2211, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1811, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1412, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1912, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2710, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1910, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1511, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.0911, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2011, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.0711, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1211, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2012, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1908, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2911, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1811, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1712, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1612, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1512, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1711, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1512, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1609, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2111, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1209, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.2312, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1111, grad_fn=<NllLossBackward0>)\n",
      "tensor(2.1411, grad_fn=<NllLossBackward0>)\n"
     ]
    }
   ],
   "source": [
    "loss_list = []\n",
    "for i in range(50):\n",
    "    for x,y in train_loader:\n",
    "        optim.zero_grad()\n",
    "        pred = model(x.reshape(batch_size,784),p)\n",
    "        loss = loss_fn(pred,y)\n",
    "        loss_list.append(loss)\n",
    "        loss.backward()\n",
    "        optim.step()\n",
    "    print(loss)\n",
    "plt.plot(loss_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
